package com.demo.security.util;


import com.demo.security.model.SysUser;
import com.demo.security.service.UserService;
import com.demo.utils.SpringContextHolder;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

@Component
public class JwtTokenUtil implements Serializable {


    public static final long TOKEN_VALIDITY = 60 * 60 * 5; //token有效期
    private static final String secret = "xiaoDong_secret";

    private static String AUTHORIZE_TOKEN_SERVICE_KEY = "UserService";

    public static String getCodeFromToken(String token) {
        return getClaimFromToken(token, Claims::getSubject);
    }

    public static Date getIssuedAtDateFromToken(String token) {
        return getClaimFromToken(token, Claims::getIssuedAt);
    }

    public static Date getExpirationDateFromToken(String token) {
        return getClaimFromToken(token, Claims::getExpiration);
    }

    public static <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = getAllClaimsFromToken(token);
        return claimsResolver.apply(claims);
    }

    private static Claims getAllClaimsFromToken(String token) {
        return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
    }

    private static Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        System.out.println("token验证:expiration:"+ expiration);
        return expiration.before(new Date());
    }

    private static Boolean ignoreTokenExpiration(String token) {
        return false;
    }

    public  static String generateToken(UserDetails userDetails) {
        UserService userService = getUserService();
        SysUser user = userService.getUserByName(userDetails.getUsername());
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, user.getCode());
    }
    public static String generateToken(String userName) {
        UserService userService = getUserService();
        SysUser user = userService.getUserByName(userName);
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, user.getCode());
    }
    private static String doGenerateToken(Map<String, Object> claims, String subject) {
        return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + TOKEN_VALIDITY * 1000)).signWith(SignatureAlgorithm.HS512, secret).compact();
    }

    public static Boolean canTokenBeRefreshed(String token) {
        return (!isTokenExpired(token) || ignoreTokenExpiration(token));
    }

    public static Boolean validateToken(String token, UserDetails userDetails) {
        UserService userService = getUserService();
        SysUser user = userService.getUserByName(userDetails.getUsername());
        final String userCode = getCodeFromToken(token);
        System.out.println("token验证:userCode:"+ userCode);
        return (userCode.equals(user.getCode()) && !isTokenExpired(token));
    }

    public static UserService getUserService(){
        return SpringContextHolder.getBean(AUTHORIZE_TOKEN_SERVICE_KEY);
    }

    public static void main(String[] args) {
        String name = "lxd";
        String token = generateToken(name);
        System.out.println(token);
//        System.out.println(validateToken(token,name));
    }


}
